//<<<+++OPENSOURCE
//<<<+++OPENSOURCE_LICENSE
/**
 * @addtogroup FXCRT
 * @{
 */

/**
 * @file
 * @brief Providing cryptographic algorithms
 */

//<<<+++OPENSOURCE_MUST_BEGIN
#ifndef _FX_CRYPT_H_
#define _FX_CRYPT_H_

#ifdef __cplusplus
extern "C" {
#endif
//<<<+++OPENSOURCE_MUST_END

/**
 * @name ArcFour algorithm
 * Believed to be same as RC4
 */
/*@{*/

/**
 * A simple one-pass ArcFour encryption/decryption.
 *
 * @param[in/out] data		Pointer to the data buffer. The buffer will be replaced with encrypted/decrypted data.
 * @param[in] size			Number of bytes in the data buffer.
 * @param[in] key			Pointer to the key data.
 * @param[in] keylen		Number of bytes in the key.
*/
void CRYPT_ArcFourCryptBlock(FX_LPBYTE data, FX_DWORD size, FX_LPCBYTE key, FX_DWORD keylen);

/**
 * Setup a ArcFour encryption/decryption context.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 1040 bytes!!!!
 * @param[in] key			Pointer to the key data.
 * @param[in] length		Number of bytes in the key.
*/
void CRYPT_ArcFourSetup(FX_LPVOID context, FX_LPCBYTE key, FX_DWORD length);

/**
 * Do some ArcFour encryption/decryption. FX_ArcFourSetup() must be called first.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The buffer has to be at least 1040 bytes!!!!
 * @param[in/out] data		Pointer to the data buffer. The buffer will be replaced with encrypted/decrypted data.
 * @param[in] size			Number of bytes in the data buffer.
*/
void CRYPT_ArcFourCrypt(FX_LPVOID context, FX_LPBYTE data, FX_DWORD size);

/*@}*/

/**
 * @name AES algorithm
 * Support 128, 192 and 256 bit keys.
 */
/*@{*/

/**
 * Initialize an AES context and set the key.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 2048 bytes!!!!
 * @param[in] blocklen		Number of bytes in each data block. Must be 16, 24 or 32
 * @param[in] key			Buffer for key data.
 * @param[in] keylen		Number of bytes in key. Must be 16, 24 or 32
 * @param[in] bEncrypt      Whether the key is used to encrypt.
*/
void CRYPT_AESSetKey(FX_LPVOID context, FX_DWORD blocklen, FX_LPCBYTE key, FX_DWORD keylen, FX_BOOL bEncrypt);

/**
 * Set initial vector (IV) for the AES context. CRYPT_AESSetKey() must be called first.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 2048 bytes!!!!
 * @param[in] iv			The IV buffer. Size of this buffer must be same as block size.
 */
void CRYPT_AESSetIV(FX_LPVOID context, FX_LPCBYTE iv);

/**
 * Do some AES decryption to data blocks.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 2048 bytes!!!!
 * @param[out] dest			Output buffer. The same of this buffer must be same or larger than input data.
 * @param[in] src			Source data buffer.
 * @param[in] size			Source data size, in bytes. It must be a multiplication of block size.
 */
void CRYPT_AESDecrypt(FX_LPVOID context, FX_LPBYTE dest, FX_LPCBYTE src, FX_DWORD size);

/**
 * Do some AES encryption to data blocks.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 2048 bytes!!!!
 * @param[out] dest			Output buffer. The same of this buffer must be same or larger than input data.
 * @param[in] src			Source data buffer.
 * @param[in] size			Source data size, in bytes. It must be a multiplication of block size.
 */
void CRYPT_AESEncrypt(FX_LPVOID context, FX_LPBYTE dest, FX_LPCBYTE src, FX_DWORD size);

/*@}*/

/**
 * @name MD5 hash algorithm. 
 * It's under attack so don't use it if you don't have to.
 */
/*@{*/

/** A simple one-pass MD5 hash generation.
 * @param[in] data			Input data buffer.
 * @param[in] size			Data size in bytes.
 * @param[out] digest		16-byte buffer receiving the hash value.
 */
void CRYPT_MD5Generate(FX_LPCBYTE data, FX_DWORD size, FX_BYTE digest[16]);

/**
 * Setup a MD5 context.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 100 bytes!!!!
*/
void CRYPT_MD5Start(FX_LPVOID context);

/**
 * Update the MD5 with some new data. CRYPT_MD5Start() must be called before.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 100 bytes!!!!
 * @param[in] data			Pointer to the data buffer. The buffer will be replaced with encrypted/decrypted data.
 * @param[in] size			Number of bytes in the data buffer.
*/
void CRYPT_MD5Update(FX_LPVOID context, FX_LPCBYTE data, FX_DWORD size);

/** Finish the MD5 process and output the digest.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 100 bytes!!!!
 * @param[out] digest		16-byte buffer receiving the hash value.
 */
void CRYPT_MD5Finish(FX_LPVOID context, FX_BYTE digest[16]);

/*@}*/

/**
 * @name SHA-1 hash algorithm. 
 */
/*@{*/

/** A simple one-pass SHA1 hash generation.
 * @param[in] data			Input data buffer.
 * @param[in] size			Data size in bytes.
 * @param[out] digest		20-byte buffer receiving the hash value.
 */
void CRYPT_SHA1Generate(FX_LPCBYTE data, FX_DWORD size, FX_BYTE digest[20]);

/**
 * Setup a SHA1 context.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 128 bytes!!!!
*/
void CRYPT_SHA1Start(FX_LPVOID context);

/**
 * Update the SHA1 with some new data. CRYPT_SHA1Start() must be called before.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 128 bytes!!!!
 * @param[in] data			Pointer to the source data buffer.
 * @param[in] size			Number of bytes in the data buffer.
*/
void CRYPT_SHA1Update(FX_LPVOID context, FX_LPCBYTE data, FX_DWORD size);

/** Finish the SHA1 process and output the digest.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 128 bytes!!!!
 * @param[out] digest		20-byte buffer receiving the hash value.
 */
void CRYPT_SHA1Finish(FX_LPVOID context, FX_BYTE digest[20]);

/*@}*/

/**
 * @name SHA-256 hash algorithm. 
 */
/*@{*/

/** A simple one-pass SHA256 hash generation.
 * @param[in] data			Input data buffer.
 * @param[in] size			Data size in bytes.
 * @param[out] digest		32-byte buffer receiving the hash value.
 */
void CRYPT_SHA256Generate(FX_LPCBYTE data, FX_DWORD size, FX_BYTE digest[32]);

/**
 * Setup a SHA256 context.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 128 bytes!!!!
*/
void CRYPT_SHA256Start(FX_LPVOID context);

/**
 * Update the SHA256 with some new data. CRYPT_SHA256Start() must be called before.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 128 bytes!!!!
 * @param[in] data			Pointer to the source data buffer.
 * @param[in] size			Number of bytes in the data buffer.
*/
void CRYPT_SHA256Update(FX_LPVOID context, FX_LPCBYTE data, FX_DWORD size);

/** Finish the SHA256 process and output the digest.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 128 bytes!!!!
 * @param[out] digest		32-byte buffer receiving the hash value.
 */
void CRYPT_SHA256Finish(FX_LPVOID context, FX_BYTE digest[32]);

/*@}*/

/**
 * @name SHA-384 hash algorithm. 
 */
/*@{*/

/**
 * Setup a SHA384 context.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 1024 bytes!!!!
*/
void CRYPT_SHA384Start(FX_LPVOID context);

/**
 * Update the SHA384 with some new data. CRYPT_SHA384Start() must be called before.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 1024 bytes!!!!
 * @param[in] data			Pointer to the source data buffer.
 * @param[in] size			Number of bytes in the data buffer.
*/
void CRYPT_SHA384Update(FX_LPVOID context, FX_LPCBYTE data, FX_DWORD size);

/** Finish the SHA384 process and output the digest.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 1024 bytes!!!!
 * @param[out] digest		48-byte buffer receiving the hash value.
 */
void CRYPT_SHA384Finish(FX_LPVOID context, FX_BYTE digest[48]);

/** A simple one-pass SHA384 hash generation.
 * @param[in] data			Input data buffer.
 * @param[in] size			Data size in bytes.
 * @param[out] digest		48-byte buffer receiving the hash value.
 */
void CRYPT_SHA384Generate(FX_LPCBYTE data, FX_DWORD size, FX_BYTE digest[48]);

/*@}*/

/**
 * @name SHA-512 hash algorithm. 
 */
/*@{*/

/**
 * Setup a SHA512 context.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 1024 bytes!!!!
*/
void CRYPT_SHA512Start(FX_LPVOID context);

/**
 * Update the SHA512 with some new data. CRYPT_SHA384Start() must be called before.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 1024 bytes!!!!
 * @param[in] data			Pointer to the source data buffer.
 * @param[in] size			Number of bytes in the data buffer.
*/
void CRYPT_SHA512Update(FX_LPVOID context, FX_LPCBYTE data, FX_DWORD size);

/** Finish the SHA512 process and output the digest.
 *
 * @param[in] context		A pointer to a memory block provided by the caller. 
 *							IMPORTANT: The memory block has to be at least 1024 bytes!!!!
 * @param[out] digest		64-byte buffer receiving the hash value.
 */
void CRYPT_SHA512Finish(FX_LPVOID context, FX_BYTE digest[64]);

/** A simple one-pass SHA512 hash generation.
 * @param[in] data			Input data buffer.
 * @param[in] size			Data size in bytes.
 * @param[out] digest		48-byte buffer receiving the hash value.
 */
void CRYPT_SHA512Generate(FX_LPCBYTE data, FX_DWORD size, FX_BYTE digest[64]);

/*@}*/
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
/** A platform dependant implemention of PKCS#7 message decryption
 * On platforms other than Windows desktop, application must call CRYPT_SetPubKeyDecryptor first to
 * provide the real decryptor, otherwise this function will always return failure.
 * On Windows, a decryptor has been already implemented.
 * @param[in] data			Input data buffer.
 * @param[in] size			Data size in bytes.
 * @param[in/out] data_buf		Buffer for output data
 * @param[in/out] data_len		Input: buffer size; output: data size
 * @return TRUE if successful.
 */
FX_BOOL CRYPT_PubKeyDecrypt(FX_LPCBYTE pData, FX_DWORD size, FX_LPBYTE data_buf, FX_DWORD& data_len);
    
FX_BOOL CRYPT_PubKeyDecryptByFile(IFX_FileRead* pFile, FX_LPCSTR password, FX_LPCBYTE pData, FX_DWORD size, FX_LPBYTE data_buf, FX_DWORD& data_len);
//<<<+++OPENSOURCE_END
/** Set the underlying decryptor for PKCS#7 message.
 * @param[in] func			Function pointer
 */
void CRYPT_SetPubKeyDecryptor(FX_BOOL (*func)(FX_LPCBYTE pData, FX_DWORD size, FX_LPBYTE data_buf, FX_DWORD& data_len));

//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
/** Use default decryptor for PKCS#7 message, only for windows now.
 */
void CRYPT_UseDefaultPubKeyDecryptor();
//<<<+++OPENSOURCE_END

//<<<+++OPENSOURCE_MUST_BEGIN
#ifdef __cplusplus
};
#endif

#endif	// !_FX_CRYPT_H_
//<<<+++OPENSOURCE_MUST_END

/** @} */


